package music.player

import scala.collection.mutable.Queue
import javax.sound.sampled.AudioFormat


object Effects {
  
     //Time Bend Stuff
     // TODO(1) Figure out the general cases for time bending ( add packets < 1 < drop packets )
     // 2.0 = Drop every other packet
     // 1.5 = Drop every third packet
     // 1.0 = Nothing
     // .5 = Double every packet (or do linear interpolation)
     // .33 = Triple every packet etc...
     
     
     // TODO(0) Add Pitch Bending & Time Bending w/ changing other variable (MIT license)
     // see also: http://en.wikipedia.org/wiki/Audio_time-scale/pitch_modification
  
  
  
//TODO(1) Figure out why adding reverb also adds some white noise
  class Reverb(
      private var reverbSecs:Double,
      private var reverbFalloff:Double,
      private var active:Boolean
      ) {

    def turnOn:Unit = active = true;
    def turnOff:Unit = active = false;
    def isOn:Boolean = active;
    
    //private var reverbSecs:Double = .125;	// How many seconds delay for reverb
    //private var reverbFalloff:Double = .5;	// How loud reverb is compared to the sample.
    def setReverb(seconds:Double, falloff:Double):Unit = {
      reverbSecs = seconds;
      reverbFalloff = falloff;
    }
    
    private val Q:Queue[Sample] = new Queue();
    
    def clearReverb(format:AudioFormat):Unit = {
      Q.clear();
      format.getFrameSize()
      val reverbSamples:Int = (format.getFrameRate() * reverbSecs).toInt;
      for(val temp <- 0 to reverbSamples) 
        Q.enqueue(
          Sample( for(i <- 0 to format.getFrameSize()) yield 0.toByte )
        )
    }
    
    def apply(s:Sample):Sample = {
      if(!this.isOn) { return s; }
      else {
         val reverbed:Sample = s + Q.dequeue();
         Q.enqueue(reverbed * reverbFalloff);
         return reverbed;
      }
    }
  }
  
  object Reverb {
    def apply(seconds:Double, falloff:Double, active:Boolean):Reverb = new Reverb(seconds,falloff,active);
  }
  
}